<?php
/**
 * Created by PhpStorm
 * User: Jhinwy
 * Date: 4/24/24
 * Time: 2:01 PM
 */

namespace app\common\service\media;

use app\common\model\media\Media;
use app\common\model\media_account\MediaAccount;
use app\common\model\media_account\MediaAuth;
use app\common\model\recycle_report\RecycleReport;
use GuzzleHttp\Client;
use GuzzleHttp\RequestOptions;
use think\facade\Cache;
use think\facade\Log;

class VivoService
{
    const REDIS_MEDIA_VIVO_TOKEN     = 'redis_media_vivo_token_';
    const REDIS_MEDIA_VIVO_REF_TOKEN = 'redis_media_vivo_ref_token_';


    protected $clientId;
    protected $secret;

    public function __construct($authId)
    {
        $mediaAuth      = MediaAuth::where('id', $authId)->findOrEmpty();
        $this->config   = config('media.vivo') ?? [];
        $this->clientId = $mediaAuth->app_id ?? '';
        $this->secret   = $mediaAuth->secret ?? '';
    }


    public function getEmpowerUrl($state = 0)
    {
        $redirect_uri = env('app.host') . $this->config['redirect_uri'];
        return sprintf(
            $this->config['empower_url'] ?? '',
            $this->clientId,
            $state,
            urlencode($redirect_uri),
            );
    }


    public function getToken($authCode)
    {
        try {
            $url = $this->config['token_api']
                . '?client_id=' . $this->clientId
                . '&client_secret=' . $this->secret
                . '&grant_type=code&code=' . $authCode;

            Log::write('请求VIVO授权Token==>' . $url, 'info');
            $client   = new Client();
            $response = $client->request('GET', $url);
            if ($response->getStatusCode() !== 200) {
                throw new \Exception('请求失败');
            }
            $contents    = $response->getBody()->getContents();
            $data        = json_decode($contents, true);
            $accessToken = $this->cacheToken($data, $this->clientId);
            if (!$accessToken) {

                throw new \Exception('无效的Token');
            }

            return $accessToken;
        } catch (\Exception $exception) {
            Log::error('获取VIVO token失败：' . $exception->getMessage());

            return false;
        }
    }


    /**
     * 缓存token
     *
     * @param $data
     * @return array|bool
     */
    public function cacheToken($data, $clientId)
    {
        Log::write('缓存VIVO授权Token==>' . json_encode($data), 'info');
        $data                 = $data['data'] ?? [];
        $accessToken          = $data['access_token'] ?? '';
        $accessTokenExpiresIn = $data['token_date'] ?? '';
        $refToken             = $data['refresh_token'] ?? 0;
        $refTokenIn           = $data['refresh_token_date'] ?? 0;

        if (!$accessToken || !$accessTokenExpiresIn || !$refToken || !$refTokenIn) {

            return false;
        }

        // 缓存巨量Token
        Cache::set(self::REDIS_MEDIA_VIVO_TOKEN . $clientId, $accessToken, $accessTokenExpiresIn);
        Cache::set(self::REDIS_MEDIA_VIVO_REF_TOKEN . $clientId, $refToken, $refTokenIn);

        return $accessToken;
    }


    /**
     * 获取缓存token
     *
     * @return bool|mixed
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function getCacheToken($clientId)
    {
        if ($accessToken = Cache::get(self::REDIS_MEDIA_VIVO_TOKEN . $clientId)) {

            return $accessToken;
        }
        // token过期刷新快手token
        if ($refToken = Cache::get(self::REDIS_MEDIA_VIVO_REF_TOKEN . $clientId)) {
            if ($accessToken = $this->refToken($refToken)) {

                return $accessToken;
            }
        }

        return false;
    }


    /**
     * 刷新快手token
     *
     * @param $refToken
     * @return bool
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function refToken($refToken)
    {
        try {
            $url = $this->config['ref_token_api']
                . '?client_id=' . $this->clientId
                . '&client_secret=' . $this->secret
                . '&refresh_token=' . $refToken;

            $client   = new Client();
            $response = $client->request('GET', $url);
            if ($response->getStatusCode() !== 200) {
                throw new \Exception('请求失败');
            }
            $contents    = $response->getBody()->getContents();
            $data        = json_decode($contents, true);
            $accessToken = $this->cacheToken($data, $this->clientId);
            if (!$accessToken) {

                throw new \Exception('无效的Token');
            }

            return $accessToken;
        } catch (\Exception $exception) {
            Log::error('刷新快手token失败：' . $exception->getMessage());

            return false;
        }
    }


    /**
     * 获取广告主
     *
     * @param $advertiserId
     * @param $token
     * @param $userName
     * @return bool|int
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function getAdvertiser($authId, $token)
    {
        try {
            $headers = [
                'Content-Type' => 'application/json',
            ];
            $fields  = [
                'pageSize' => 100
            ];
            $client  = new Client();
            Log::info('【请求VIVO广告主信息】' . $this->formatUrl($this->config['advertiser_api'] ?? '', $token));
            $response = $client->request(
                'POST',
                $this->formatUrl($this->config['advertiser_api'] ?? '', $token),
                [
                    'headers'            => $headers,
                    'timeout'            => 60,
                    RequestOptions::JSON => $fields
                ]
            );

            if ($response->getStatusCode() !== 200) {
                throw new \Exception('请求失败');
            }
            $contents = $response->getBody()->getContents();
            Log::info('【VIVO广告主信息】' . $contents);
            $data = json_decode($contents, true);
            if (!$data = $data['data']['list'] ?? []) {
                throw new \Exception('广告主信息不存在');
            }

            $insertData = [];
            foreach ($data as $item) {
                if (MediaAccount::where('advertiser_id', $item['uuid'] ?? 0)->where('media_id', Media::SOURCE_VIVO)->findOrEmpty()->isEmpty()) {
                    $insertData[] = [
                        'media_auth_id'      => $authId,
                        'auth_advertiser_id' => $this->clientId,
                        'advertiser_id'      => $item['uuid'] ?? 0,
                        'advertiser_name'    => $item['name'] ?? '',
                        'company'            => '',
                        'admin_id'           => 0,
                        'media_id'           => Media::SOURCE_VIVO,
                        'status'             => $item['status'] ?? 0,
                        'create_time'        => time(),
                        'update_time'        => time()
                    ];
                }
            }

            return MediaAccount::insertAll($insertData);
        } catch (\Exception $exception) {
            Log::error('获取百度授权广告主失败：' . $exception->getMessage());

            return false;
        }
    }


    /**
     * 格式化请求连接
     *
     * @param $url
     * @param $token
     * @return string
     */
    private function formatUrl($url, $token)
    {
        $time = msectime();

        return $url . '?access_token=' . $token . '&timestamp=' . $time . '&nonce=' . md5($time . rand(1000, 9999));
    }
}
